%----------------------------------
% 图形相关的项
% 需要 TexLive 2020 版本

% 自定义填充格式，用于实现绘制阴影
% TikZ 提供的 north east lines 等默认 pattern, 或 Lines ，有个问题：使用不同的PDF阅读器，会得到不同的效果。
% 如：
%       VSCode 中 LaTeX WorkShop 看到的是线段，
%       SumatraPDF 看到的是连贯的线条。
% 所以这里采用自定义的格式。
% 下面的代码基本是将 Lines 的代码修改而成。
% Lines实现中，bounding box 是 (-0.5\distance, -0.5\distance) 到 (0.5\distance, 0.5\distance)
% 这里的 TikZ 实现是 (0, 0) 到 (\distance, \distance)，按说应该没有区别，但实际效果确有不同。
\pgfdeclarepattern{
  name=mylines,
  parameters={
      \pgfkeysvalueof{/pgf/pattern keys/distance},
      \pgfkeysvalueof{/pgf/pattern keys/angle},
      \pgfkeysvalueof{/pgf/pattern keys/xshift},
      \pgfkeysvalueof{/pgf/pattern keys/yshift},
      \pgfkeysvalueof{/pgf/pattern keys/line width},
  },
  bottom left={%
    \pgfpoint
      {0}%
      {0}},
  top right={%
    \pgfpoint
      {(\pgfkeysvalueof{/pgf/pattern keys/distance})}%
      {(\pgfkeysvalueof{/pgf/pattern keys/distance})}},
  tile size={%
    \pgfpoint
      {\pgfkeysvalueof{/pgf/pattern keys/distance}}%
      {\pgfkeysvalueof{/pgf/pattern keys/distance}}},
  tile transformation={%
    \pgftransformshift{%
      \pgfpoint
        {\pgfkeysvalueof{/pgf/pattern keys/xshift}}%
        {\pgfkeysvalueof{/pgf/pattern keys/yshift}}}%
    \pgftransformrotate{\pgfkeysvalueof{/pgf/pattern keys/angle}}},
  defaults={
    distance/.initial=3pt,
    angle/.initial=0,
    xshift/.initial=0pt,
    yshift/.initial=0pt,
    line width/.initial=\the\pgflinewidth,
  },
  code={%
    \pgfsetlinewidth{\pgfkeysvalueof{/pgf/pattern keys/line width}}%
    \pgfpathmoveto{\pgfpoint{0pt}{0pt}}%
    \pgfpathlineto{\pgfpoint{(\pgfkeysvalueof{/pgf/pattern keys/distance})}{0pt}}%
    \pgfusepath{stroke}%
  },
}


% 绘制温度计(温度范围：-10 ~ 20 ℃)
\tikzset{
    % 参数1: 显示的温度。
    pics/thermometer/.style n args={1}{
      code = {
        % 绘制外框
        \draw [thick] (-1, -0.6) -- (0.8, -0.6) -- (0.8, 6) -- (-1, 6) -- cycle;

        % 绘制玻璃管
        \draw [thick] (135:0.35) arc (135:405:0.35)
            to [out=135, in=270] (0.2, 0.5)
            -- (0.2, 6) -- (-0.2, 6) -- (-0.2, 0.5)
            to [out=270, in=45] (135:0.35);

        % 绘制刻度
        \foreach \y in {1,...,7} {
            \ifnum \y<3
                \def\value{\the\numexpr5*(3-\y)}
            \else
                \def\value{\the\numexpr5*(\y-3)}
            \fi
            \draw (-0.2,0.5+0.7*\y) -- (-0.4,0.5+0.7*\y) node[anchor=east] {$\value$};
            \ifnum \y < 7
                \foreach \tmp in {1,...,4} {
                    \draw (-0.2,0.5+0.7*\y+0.14*\tmp) -- (-0.3,0.5+0.7*\y+0.14*\tmp);
                }
            \fi
        }

        % 绘制水银柱
        \def\h{\the\numexpr0.5+2.1+0.14*#1}
        \draw [black!80, fill] (135:0.3) arc (135:405:0.3)
            to [out=135, in=270] (0.15, 0.4)
            -- (0.15, \h) -- (-0.15, \h) -- (-0.15, 0.4)
            to [out=270, in=45] (135:0.3);
      }
    }
}


% 用于填充的水面的纹路
\tikzset{
    waterwave/.pic={
        \draw [dash=on 17pt off 2pt phase 0pt] (0, -0.01) -- (10, -0.01);
        \draw [dash=on 15pt off 3pt phase 0pt] (0, -0.1)  -- (10, -0.1);
        \draw [dash=on 10pt off 4pt phase 0pt] (0, -0.2)  -- (10, -0.2);
        \draw [dash=on 9pt off 3pt phase 0pt]  (0, -0.3)  -- (10, -0.3);
        \draw [dash=on 6pt off 2pt phase 0pt]  (0, -0.4)  -- (10, -0.4);
        \draw [dash=on 4pt off 2pt phase 0pt]  (0, -0.5)  -- (10, -0.5);
        \draw [dash=on 3pt off 2pt phase 0pt]  (0, -0.6)  -- (10, -0.6);
    }
}

% 路面样式（用于修改 Path）
\tikzset{
    ground/.style={ground/.cd, #1, wrapper},
    ground/.cd,
      angle/.initial=-45,
      wrapper/.style={/tikz/.cd,
        postaction={
          draw,
          decorate,
          decoration={
            border,
            angle=\pgfkeysvalueof{/tikz/ground/angle},
            amplitude=0.3cm,
            segment length=2mm}}
      },
}


% 绘制一个箭头。
% 共有四个参数：
%   1. （箭头下部矩形）的底的长度
%   2. （箭头下部矩形）的高的长度
%   3. （箭头上部三角形）的底的长度
%   4. （箭头上部三角形）的高的长度
% 调用的例子：
%   \draw [fill=white] (0, 0) pic {arrow={.2}{.3}{.4}{.2}};
%   \draw [red, thick, pattern=dots] (0, 0) pic [rotate=90] {arrow={.2}{.3}{.4}{.2}};
\tikzset{
    pics/arrow/.style n args={4}{
      code = {
        \filldraw [pic actions] (-#1/2, 0) -- (#1/2, 0) -- (#1/2, #2)
            -- (#3/2, #2) -- (0, #2+#4)
            -- (-#3/2, #2) -- (-#1/2, #2)
            -- cycle;
    }}}


% 绘制立方体 （ 代码改编自 https://tex.stackexchange.com/a/48776/121799 ）
% 依赖的库：
%   \usetikzlibrary{3d}
% 共有六个参数：
%   1. X 的最小值
%   2. X 的最大值
%   3. Y 的最小值
%   4. Y 的最大值
%   5. Y 的最小值
%   6. Y 的最大值
% 调用举例：以步进 0.5，使用粗线条，绘制一个 3 * 2 * 2 的立方体。
%   \draw [step=0.5, thick] (0, 0) pic {cubes={0}{3}{0}{2}{0}{2}};
\tikzset{
    pics/cubes/.style n args={6}{
      code = {
        \def\XGridMin{#1}
        \def\XGridMax{#2}
        \def\YGridMin{#3}
        \def\YGridMax{#4}
        \def\ZGridMin{#5}
        \def\ZGridMax{#6}
         %
        \begin{scope}[canvas is xy plane at z=\ZGridMax]
            \draw [pic actions] (\XGridMin,\YGridMin) grid (\XGridMax,\YGridMax);
        \end{scope}
        \begin{scope}[canvas is yz plane at x=\XGridMax]
            \draw [pic actions] (\YGridMin,\ZGridMin) grid (\YGridMax,\ZGridMax);
        \end{scope}
        \begin{scope}[canvas is xz plane at y=\YGridMax]
            \draw [pic actions] (\XGridMin,\ZGridMin) grid (\XGridMax,\ZGridMax);
        \end{scope}
    }
  }
}


% 绘制两端有竖线的线段
\tikzset{
  xianduan/.style={xianduan/.cd, #1, wrapper},
  xianduan/.cd,
    above/.store in=\above,  above=0.5em,
    below/.store in=\below,  below=0.5em,
    wrapper/.style={/tikz/.cd, to path={
        ($(\tikztostart)!\above!90:(\tikztotarget)$)  -- ($(\tikztostart)!\below!-90:(\tikztotarget)$)
        ($(\tikztotarget)!\above!-90:(\tikztostart)$) -- ($(\tikztotarget)!\below!90:(\tikztostart)$)
        (\tikztostart) -- (\tikztotarget) \tikztonodes
    }}
}


% 绘制垂足
% 注：可以使用 Angle Library 提供的 right angle 替换掉本命令（chuizu）
\tikzset{
    chuizu/.style={chuizu/.cd, #1, wrapper},
    chuizu/.cd,
        size/.store in=\size,   size=0.5em,
        % （从上至下画线时）垂足在显示的方位：right表示显示在右侧（缺省值），left表示在左侧）
        direction/.is choice,
            direction/right/.code = {\def\chuizuangle{-90}},
            direction/left/.code  = {\def\chuizuangle{90}},
            direction=right,
        skipline/.is choice,
            skipline/true/.code  = {\def\mainpath{(\tikztostart)    (\tikztotarget)}},
            skipline/false/.code = {\def\mainpath{(\tikztostart) -- (\tikztotarget)}},
            skipline=false,
        wrapper/.style={/tikz/.cd, to path={
            ($(\tikztotarget)!\size!0:(\tikztostart)$)
                -- ($(\tikztotarget)!1.414*\size!0.5*\chuizuangle:(\tikztostart)$)
                -- ($(\tikztotarget)!\size!\chuizuangle:(\tikztostart)$)
            \mainpath \tikztonodes
        }}
}


% 在数轴上绘制区间
\tikzset{
  interval/.pic={
    \begin{scope}[interval options/.cd,#1]
      \pgfkeysgetvalue{/tikz/interval options/start}{\start}
      \pgfkeysgetvalue{/tikz/interval options/stop}{\stop}
      \pgfkeysgetvalue{/tikz/interval options/height}{\height}
      \pgfmathsetmacro{\sign}{\start < \stop ? 1 : -1}
      \pgfmathsetmacro{\posOne}{\sign * 0.2}
      \pgfmathsetmacro{\posTwo}{\sign * 0.5}

      \ifthenelse {\infinity = 1} {
        \draw (\start, 0) .. controls (\start+\posOne, \height) and (\start+\posTwo, \height) .. (\start+\posTwo, \height)
          -- (\stop, \height);
      } {
        \draw (\start, 0) .. controls (\start+\posOne, \height) and (\start+\posTwo, \height) .. (\start+\posTwo, \height)
          -- (\stop-\posTwo, \height) .. controls (\stop-\posTwo, \height) and (\stop-\posOne, \height) .. (\stop, 0);
      }
    \end{scope}
  },
  interval options/.is family,
  interval options/.cd,
    start/.initial=0,    % 指定参数 start 的默认值
    stop/.initial=1,     % 指定参数 stop 的默认值
    height/.initial=1,   % 指定参数 height 的默认值
    infinity/.is choice, % 是否是 无限区间。 true: 无限区间； false: 有限区间。
      infinity/true/.code  = {\pgfmathsetmacro{\infinity}{1}},
      infinity/false/.code = {\pgfmathsetmacro{\infinity}{0}},
      infinity=false,    % 缺省为：有限区间
}


% 绘制 “十字相乘法”
% 共有四个参数：
%   1. a_1
%   2. a_2
%   3. c_1
%   4. c_2
\tikzset{
  pics/cross/.style n args={4}{
    code = {
      \begin{scope}[every node/.style={minimum width=3em}]
        \node [align=right] (a1) at (0, 1) {$#1$};
        \node [align=right] (a2) at (0, 0) {$#2$};
        \node [align=left] (c1) at (3, 1) {$#3$};
        \node [align=left] (c2) at (3, 0) {$#4$};
        \draw (a2.east) -- (c1.west);
        \draw (a1.east) -- (c2.west);
      \end{scope}
    }
  }
}


% 绘制 “山”
\tikzset{
  mountain/.pic={
    \draw [thick, rounded corners] (0, 0) -- (2, 0)
      .. controls (6, 1) and (8, 4) .. (9, 8)
      .. controls (14, 16) and (7, 22) .. (10, 34)
      .. controls (9, 40) and (-1, 40) .. (-2, 34)
      -- (-5, 28)
      .. controls (-10, 10) and (-10, 6) .. (0, 0)
      ;
    \draw [thick, rounded corners] (0, 10)
      .. controls (2, 11) and (5, 16) .. (6, 20)
      .. controls (3, 26) and (7, 30) .. (4, 32)
      .. controls (0, 28) and (1, 26) .. (0, 24)
      .. controls (-3, 22) and (-5, 14) .. (-2, 12)
      .. controls (-2, 11) and (-2, 8) .. (0, 10)
      ;
    \draw [thick, rounded corners] (0, 14)
      .. controls (1, 14) and (5, 20) .. (2, 23)
      .. controls (1.1, 21) and (0.4, 19.5) .. (1, 20)
      .. controls (-1.5, 18) and (-2, 15) .. (0, 14)
      ;
    \begin{scope} [rotate around={-40:(0, 17)}]
      \draw [fill=black] (-2.5, 16) rectangle (3.5, 17);
    \end{scope}
  }
}


% ---------------

% tkz-euclide 中，想要对一个角进行标识，要分两步：
%     1. “标记”（tkzMarkAngle）：绘制表示角的弧线
%     2. “标注”（tkzLabelAngle）： 给角编号（或名字）。如：$1$，$\alpha$
%  由于在这两个命令中都要写组成角的三个点，感觉很麻烦。
%  所以，提供一个命令实现简单的“标记”（Mark）和“标注”（Label）
%  "简单"是指，仅绘制弧线和指定角的编号（或名字）
\def\extkzLabelAngel[#1](#2,#3,#4)#5{%
\begingroup
  \pgfmathsetmacro{\anglepos}{0.3+#1}
  \tkzMarkAngle[size=#1](#2,#3,#4)
  \tkzLabelAngle[pos=\anglepos](#2,#3,#4){#5}
\endgroup
}


